<!doctype html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>JS Application DbC Example</title>
    <script src="../src/jsa.js" type="text/javascript"></script>
    <script src="../src/jsa.dbc.js" type="text/javascript"></script>
    <style>
        p {
            margin: 0;
        }
        .exception {
            color: red;
        }
    </style>
</head>
<body>

<script  type="text/javascript">
(function( jsa, undefined ) {
    "use strict";
    var ContractSample1 = {
        methodA : [ "number", "string" ]
    },
    ContractSample2 = {
        methodA : {
            onEntry:  [ "string", jsa.BaseAbstract ],
            validators: [
                function( arg ){ return arg.length < 20; },
                function( arg ){ return true },
            ],
            onExit: "boolean"
        },
        methodB : {
            onEntry:  [],
            onExit: "number"
        }
    },
    ModuleSample1 = function() {
        return {
            __contract__: ContractSample1
        };
    },
    ModuleSample2 = function() {
        return {
            __extends__: jsa.BaseAbstract,
            __contract__: ContractSample1,
            methodA: function() {
                print( "ModuleSample2: methodA is running" );
            }
       };
    }, ModuleSample3 = function() {
        return {
            __contract__: ContractSample2,
            methodA: function() {
                print( "ModuleSample3: methodA is running" );
                return true;
            },
            methodB: function() {
                print( "ModuleSample3: methodB is running" );
                return true;
            }
       };
    },

    /**
    * Usage
    */
    _print = function( text ) {
        document.writeln( text );
    },
    print = function( text ) {
        _print( '<p>' + text + '</p>' );
    },
    printErr = function( text ) {
        _print( '<p class="exception">' + text + '</p>' );
    };

    print( 'Sample 1. Module violates the contract' );
    try {
        ModuleSample1.createInstance();
    } catch ( e ) {
        printErr( e );
    }

    var m2 = ModuleSample2.createInstance(),
        m3 = ModuleSample3.createInstance();
    print( 'Sample 2. Module fails on contract preconditions' );
    try {
        m2.methodA( "a string where a number excpected", {} );
    } catch ( e ) {
        printErr( e );
    }
    print( 'Sample 2. Module passes contract preconditions' );
    m2.methodA( 42, "string" );
    m3.methodA( "short string", m2 ); // m2 is an instance of BaseAbstract
    print( 'Sample 3. Module fails on contract validator' );
    try {
        m3.methodA( "string, which is more than 20 chars", m2 );
    } catch( e ) {
        printErr( e );
    }
    print( 'Sample 4. Module fails on contract postcondition' );
    try {
        m3.methodB();
    } catch ( e ) {
        printErr( e );
    }

// Output:
// Sample 1. Module violates the contract
// SyntaxError: Contract requires 'methodA' method
// Sample 2. Module fails on contract preconditions
// TypeError: Argument #1 of method 'methodA' is required to be a 'number'
// Sample 2. Module passes contract preconditions
// ModuleSample2: methodA is running
// ModuleSample3: methodA is running
// Sample 3. Module fails on contract validator
// RangeError: Argument #1 of method 'methodA' is outside of its valid range
// Sample 4. Module fails on contract postcondition
// ModuleSample3: methodB is running
// TypeError: Method 'methodB' return value is required to be a number

})( jsa );
</script>

    </body>
</html>